// Copyright (c) 2025, 大连理工大学 (Dalian University of Technology)
//
// Licensed under the Mulan PSL v2.
// You can use this file according to the terms and conditions of the Mulan PSL v2.
// You may obtain a copy of the License at
//
//     http://license.coscl.org.cn/MulanPSL2
//
// THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
// EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. SEE THE MULAN PSL v2
// FOR MORE DETAILS.

#include <vector>
#include <chrono>

#include <gtest/gtest.h>

#include "DataStructure/Input/Element/CBARData.h"
#include "DataStructure/Input/Element/CBEAMData.h"
#include "DataStructure/Input/Element/CBUSHData.h"
#include "DataStructure/Input/Element/CDAMP1Data.h"
#include "DataStructure/Input/Element/CDAMP2Data.h"
#include "DataStructure/Input/Element/CDAMP3Data.h"
#include "DataStructure/Input/Element/CDAMP4Data.h"
#include "DataStructure/Input/Element/CELAS1Data.h"
#include "DataStructure/Input/Element/CELAS2Data.h"
#include "DataStructure/Input/Element/CELAS3Data.h"
#include "DataStructure/Input/Element/CELAS4Data.h"
#include "DataStructure/Input/Element/CFASTData.h"
#include "DataStructure/Input/Element/CHBDYGData.h"
#include "DataStructure/Input/Element/CHBDYPData.h"
#include "DataStructure/Input/Element/CHEXAData.h"
#include "DataStructure/Input/Element/CMASS1Data.h"
#include "DataStructure/Input/Element/CMASS2Data.h"
#include "DataStructure/Input/Element/CMASS3Data.h"
#include "DataStructure/Input/Element/CMASS4Data.h"
#include "DataStructure/Input/Element/CONM1Data.h"
#include "DataStructure/Input/Element/CONM2Data.h"
#include "DataStructure/Input/Element/CONRODData.h"
#include "DataStructure/Input/Element/CPENTAData.h"
#include "DataStructure/Input/Element/CPYRAMData.h"
#include "DataStructure/Input/Element/CQUAD4Data.h"
#include "DataStructure/Input/Element/CQUADRData.h"
#include "DataStructure/Input/Element/CRODData.h"
#include "DataStructure/Input/Element/CSHEARData.h"
#include "DataStructure/Input/Element/CTETRAData.h"
#include "DataStructure/Input/Element/CTRIA3Data.h"
#include "DataStructure/Input/Element/CVISCData.h"
#include "DataStructure/Input/Element/CWELDData.h"

#include "DBManager/DBAPI.h"
#include "DBManager/DBServiceFactory.h"
#include "DBManager/IService/Input/Element/IElementService.h"
#include "DBManager/IService/Input/Element/IPartitionElementCacheService.h"
#include "DBManager/UnitTest/HDF5/TestDB.h"

using namespace SG::DataStructure::FEM;
using namespace SG::DBManager;

class I_ElementTest : public testing::Test
{
  public:
    static void SetUpTestSuite ()
    {
        DB::ServiceFactory->ClearDatabase ();
    }

    void SetUp () override
    {
        if (service == nullptr)
        {
            service = DB::ServiceFactory->get<IElementService> ().get ();
        }
    }

    static SG::DBManager::IElementService* service;
};

SG::DBManager::IElementService* I_ElementTest::service = nullptr;

TEST_F (I_ElementTest, CBARRepository)
{
    {
        SG::DataStructure::Common::Id const id = 100001;

        // 创建对象
        SG::DataStructure::FEM::CBARData obj;
        obj.m_id   = id;
        obj.m_pId  = 1;  // 属性ID
        obj.m_g[0] = 1;
        obj.m_g[1] = 2;

        // 添加对象
        service->Add (obj);
    }
    {
        SG::DataStructure::Common::Id const id = 100002;

        // 创建对象
        SG::DataStructure::FEM::CBARData obj;
        obj.m_id   = id;
        obj.m_g[0] = 3;
        obj.m_g[1] = 4;
        // 添加对象
        service->Add (obj);
    }

    CBARData x;
    service->FindByIndex (0, x);
    ASSERT_EQ (x.m_id, 100001);

    // ASSERT_EQ (service->FindElement(100001).second, 0);
}

TEST_F (I_ElementTest, CBEAMRepository)
{
    SG::DataStructure::Common::Id const id = 100003;

    // 创建对象
    SG::DataStructure::FEM::CBEAMData obj;
    obj.m_id   = id;
    obj.m_pId  = 1;  // 属性ID
    obj.m_g[0] = 1;
    obj.m_g[1] = 2;
    // obj.m_g[2] = 3;

    // 添加对象
    service->Add (obj);

    CBEAMData x;
    service->FindByIndex (0, x);
    ASSERT_EQ (x.m_id, id);
}

TEST_F (I_ElementTest, CBUSRepository)
{
    SG::DataStructure::Common::Id const id = 100004;

    // 创建对象
    SG::DataStructure::FEM::CBUSHData obj;
    obj.m_id  = id;
    obj.m_pId = 1;  // 属性ID

    // 添加对象
    service->Add (obj);

    CBUSHData x;
    service->FindByIndex (0, x);
    ASSERT_EQ (x.m_id, 100004);
}

TEST_F (I_ElementTest, CHEXARepository)
{
    {
        SG::DataStructure::Common::Id const id = 38;

        // 创建对象
        SG::DataStructure::FEM::CHEXA8Data obj;
        obj.m_id = id;

        // 添加对象
        service->Add (obj);
    }
    {
        SG::DataStructure::Common::Id const id = 320;

        // 创建对象
        SG::DataStructure::FEM::CHEXA20Data obj;
        obj.m_id = id;

        // 添加对象
        service->Add (obj);
    }
    CHEXA8Data x;

    service->FindByIndex (0, x);
    ASSERT_EQ (x.m_id, 38);

    CHEXA20Data x20;
    service->FindByIndex (0, x20);
    ASSERT_EQ (x20.m_id, 320);
}

TEST_F (I_ElementTest, CONM1Repository)
{
    {
        SG::DataStructure::Common::Id const id = 4;

        // 创建对象
        SG::DataStructure::FEM::CONM1Data obj;
        obj.m_id = id;

        // 添加对象
        service->Add (obj);
    }
    CONM1Data x;
    service->FindByIndex (0, x);
    ASSERT_EQ (x.m_id, 4);
}

TEST_F (I_ElementTest, CONM2Repository)
{
    {
        SG::DataStructure::Common::Id const id = 5;

        // 创建对象
        SG::DataStructure::FEM::CONM2Data obj;
        obj.m_id = id;

        // 添加对象
        service->Add (obj);
    }
    CONM2Data x;
    service->FindByIndex (0, x);
    ASSERT_EQ (x.m_id, 5);
}

TEST_F (I_ElementTest, CPENTARepository)
{
    {
        SG::DataStructure::Common::Id const id = 66;

        // 创建对象
        SG::DataStructure::FEM::CPENTA6Data obj;
        obj.m_id = id;

        // 添加对象
        service->Add (obj);
    }
    {
        SG::DataStructure::Common::Id const id = 615;

        // 创建对象
        SG::DataStructure::FEM::CPENTA15Data obj;
        obj.m_id = id;

        // 添加对象
        service->Add (obj);
    }
    CPENTA6Data x;
    service->FindByIndex (0, x);
    ASSERT_EQ (x.m_id, 66);

    CPENTA15Data x15;
    service->FindByIndex (0, x15);
    ASSERT_EQ (x15.m_id, 615);
}
TEST_F (I_ElementTest, CQUAD4Repository)
{
    {
        SG::DataStructure::Common::Id const id = 8;

        // 创建对象
        SG::DataStructure::FEM::CQUAD4Data obj;
        obj.m_id   = id;
        obj.m_g[0] = 1;
        obj.m_g[1] = 2;
        obj.m_g[2] = 3;
        obj.m_g[3] = 4;

        // 添加对象
        service->Add (obj);
    }
    CQUAD4Data x;

    service->FindByIndex (0, x);
    ASSERT_EQ (x.m_id, 8);
}

TEST_F (I_ElementTest, CSHEARRepository)
{
    {
        SG::DataStructure::Common::Id const id = 9;

        // 创建对象
        SG::DataStructure::FEM::CSHEARData obj;
        obj.m_id = id;

        // 添加对象
        service->Add (obj);
    }
    CSHEARData x;

    service->FindByIndex (0, x);
    ASSERT_EQ (x.m_id, 9);
}
TEST_F (I_ElementTest, CONRODRepository)
{
    {
        SG::DataStructure::Common::Id const id = 11;

        // 创建对象
        SG::DataStructure::FEM::CONRODData obj;
        obj.m_id = id;

        // 添加对象
        service->Add (obj);
    }
    CONRODData x;

    service->FindByIndex (0, x);
    ASSERT_EQ (x.m_id, 11);
}
TEST_F (I_ElementTest, CRODRepository)
{
    {
        SG::DataStructure::Common::Id const id = 12;

        // 创建对象
        SG::DataStructure::FEM::CRODData obj;
        obj.m_id = id;

        // 添加对象
        service->Add (obj);
    }
    CRODData x;
    service->FindByIndex (0, x);
    ASSERT_EQ (x.m_id, 12);
}

TEST_F (I_ElementTest, CELAS1Repository)
{
    {
        SG::DataStructure::Common::Id const id = 13;

        // 创建对象
        SG::DataStructure::FEM::CELAS1Data obj;
        obj.m_id = id;

        // 添加对象
        service->Add (obj);
    }
    CELAS1Data x;

    service->FindByIndex (0, x);
    ASSERT_EQ (x.m_id, 13);
}

TEST_F (I_ElementTest, CTETRARepository)
{
    {
        SG::DataStructure::Common::Id const id = 144;

        // 创建对象
        SG::DataStructure::FEM::CTETRA4Data obj;
        obj.m_id = id;

        // 添加对象
        service->Add (obj);
    }
    {
        SG::DataStructure::Common::Id const id = 1410;

        // 创建对象
        SG::DataStructure::FEM::CTETRA10Data obj;
        obj.m_id = id;

        // 添加对象
        service->Add (obj);
    }
    CTETRA4Data x;
    service->FindByIndex (0, x);
    ASSERT_EQ (x.m_id, 144);

    CTETRA10Data x10;
    auto         service10 = DB::ServiceFactory->get<IElementService> ();
    service10->FindByIndex (0, x10);
    ASSERT_EQ (x10.m_id, 1410);
}

TEST_F (I_ElementTest, CTRIA3Repository)
{
    {
        SG::DataStructure::Common::Id const id = 15;

        // 创建对象
        SG::DataStructure::FEM::CTRIA3Data obj;
        obj.m_id   = id;
        obj.m_g[0] = 1;
        obj.m_g[1] = 2;
        obj.m_g[2] = 3;

        // 添加对象
        service->Add (obj);
    }

    CTRIA3Data x;

    service->FindByIndex (0, x);
    ASSERT_EQ (x.m_id, 15);
}

TEST_F (I_ElementTest, CWELDRepository)
{
    {
        SG::DataStructure::Common::Id const id = 115;

        // 创建对象
        SG::DataStructure::FEM::CWELDData obj;
        obj.m_id   = id;
        obj.m_g[0] = 1;
        obj.m_g[1] = 2;

        // 添加对象
        service->Add (obj);
    }

    CWELDData x;
    service->FindByIndex (0, x);
    ASSERT_EQ (x.m_id, 115);

    auto allData = service->GetAllData<CWELDData> ();
    ASSERT_EQ (allData.size (), 1);
    ASSERT_EQ (allData[0].m_id, 115);
}

TEST_F (I_ElementTest, CPYRAMRepository)
{
    {
        SG::DataStructure::Common::Id const id = 175;

        // 创建对象
        SG::DataStructure::FEM::CPYRAM5Data obj;
        obj.m_id   = id;
        obj.m_g[0] = 1;
        obj.m_g[1] = 2;
        obj.m_g[2] = 3;

        // 添加对象
        service->Add (obj);
    }
    {
        SG::DataStructure::Common::Id const id = 1713;

        // 创建对象
        SG::DataStructure::FEM::CPYRAM13Data obj;
        obj.m_id = id;
        for (size_t i = 0; i < 13; i++)
        {
            obj.m_g[i] = 8;
        }

        // 添加对象
        service->Add (obj);
    }
    CPYRAM5Data x;
    service->FindByIndex (0, x);
    ASSERT_EQ (x.m_id, 175);

    CPYRAM13Data x13;
    auto         service13 = DB::ServiceFactory->get<IElementService> ();
    service13->FindByIndex (0, x13);
    ASSERT_EQ (x13.m_id, 1713);
}

TEST_F (I_ElementTest, CHBDYPRepository)
{
    SG::DataStructure::Common::Id const id = 18;

    // 创建对象
    SG::DataStructure::FEM::CHBDYPData obj;
    obj.m_id   = id;
    obj.m_g[0] = 1;
    obj.m_g[1] = 2;

    // 添加对象
    service->Add (obj);
    CHBDYPData x;
    service->FindByIndex (0, x);
    ASSERT_EQ (x.m_id, 18);
}

TEST_F (I_ElementTest, CQUADRRepository)
{
    {
        SG::DataStructure::Common::Id const id = 19;

        // 创建对象
        SG::DataStructure::FEM::CQUADRData obj;
        obj.m_id = id;

        // 添加对象
        service->Add (obj);
    }
    CQUADRData x;
    service->FindByIndex (0, x);
    ASSERT_EQ (x.m_id, 19);
}

TEST_F (I_ElementTest, CDAMP1Test)
{
    SG::DataStructure::FEM::CDAMP1Data data;
    data.m_id = 100005;
    service->Add (data);

    SG::DataStructure::FEM::CDAMP1Data _OUT outData;
    service->FindById (100005, outData);
    ASSERT_EQ (outData.m_id, 100005);

    ASSERT_EQ (service->FindByIndex (0, outData), SG::DataStructure::Common::Status::STATUS_Success);

    ASSERT_EQ (outData.m_id, 100005);

    ASSERT_EQ (service->Size<CDAMP1Data> (), 1);
    ASSERT_EQ (service->Count<CDAMP1Data> (100005), 1);
}

TEST_F (I_ElementTest, CDAMP2Test)
{
    SG::DataStructure::FEM::CDAMP2Data data;
    data.m_id = 100006;
    service->Add (data);

    SG::DataStructure::FEM::CDAMP2Data _OUT outData;
    service->FindById (100006, outData);
    ASSERT_EQ (outData.m_id, 100006);

    ASSERT_EQ (service->FindByIndex (0, outData), SG::DataStructure::Common::Status::STATUS_Success);

    ASSERT_EQ (outData.m_id, 100006);

    ASSERT_EQ (service->Size<CDAMP2Data> (), 1);
    ASSERT_EQ (service->Count<CDAMP2Data> (100006), 1);
}

TEST_F (I_ElementTest, CDAMP3Test)
{
    SG::DataStructure::FEM::CDAMP3Data data;
    data.m_id = 100007;
    service->Add (data);

    SG::DataStructure::FEM::CDAMP3Data _OUT outData;
    service->FindById (100007, outData);
    ASSERT_EQ (outData.m_id, 100007);

    ASSERT_EQ (service->FindByIndex (0, outData), SG::DataStructure::Common::Status::STATUS_Success);

    ASSERT_EQ (outData.m_id, 100007);

    ASSERT_EQ (service->Size<CDAMP3Data> (), 1);
    ASSERT_EQ (service->Count<CDAMP3Data> (100007), 1);
}

TEST_F (I_ElementTest, CDAMP4Test)
{
    SG::DataStructure::FEM::CDAMP4Data data;
    data.m_id = 100008;
    service->Add (data);

    SG::DataStructure::FEM::CDAMP4Data _OUT outData;
    service->FindById (100008, outData);
    ASSERT_EQ (outData.m_id, 100008);

    ASSERT_EQ (service->FindByIndex (0, outData), SG::DataStructure::Common::Status::STATUS_Success);

    ASSERT_EQ (outData.m_id, 100008);

    ASSERT_EQ (service->Size<CDAMP4Data> (), 1);
    ASSERT_EQ (service->Count<CDAMP4Data> (100008), 1);
}

TEST_F (I_ElementTest, CELAS2Test)
{
    SG::DataStructure::FEM::CELAS2Data data;
    data.m_id = 100009;
    service->Add (data);

    SG::DataStructure::FEM::CELAS2Data _OUT outData;
    service->FindById (100009, outData);
    ASSERT_EQ (outData.m_id, 100009);

    ASSERT_EQ (service->FindByIndex (0, outData), SG::DataStructure::Common::Status::STATUS_Success);

    ASSERT_EQ (outData.m_id, 100009);

    ASSERT_EQ (service->Size<CELAS2Data> (), 1);
    ASSERT_EQ (service->Count<CELAS2Data> (100009), 1);
}

TEST_F (I_ElementTest, CELAS3Test)
{
    SG::DataStructure::FEM::CELAS3Data data;
    data.m_id = 100010;
    service->Add (data);

    SG::DataStructure::FEM::CELAS3Data _OUT outData;
    service->FindById (100010, outData);
    ASSERT_EQ (outData.m_id, 100010);

    ASSERT_EQ (service->FindByIndex (0, outData), SG::DataStructure::Common::Status::STATUS_Success);

    ASSERT_EQ (outData.m_id, 100010);

    ASSERT_EQ (service->Size<CELAS3Data> (), 1);
    ASSERT_EQ (service->Count<CELAS3Data> (100010), 1);
}

TEST_F (I_ElementTest, CELAS4Test)
{
    SG::DataStructure::FEM::CELAS4Data data;
    data.m_id = 100011;
    service->Add (data);

    SG::DataStructure::FEM::CELAS4Data _OUT outData;
    service->FindById (100011, outData);
    ASSERT_EQ (outData.m_id, 100011);

    ASSERT_EQ (service->FindByIndex (0, outData), SG::DataStructure::Common::Status::STATUS_Success);

    ASSERT_EQ (outData.m_id, 100011);

    ASSERT_EQ (service->Size<CELAS4Data> (), 1);
    ASSERT_EQ (service->Count<CELAS4Data> (100011), 1);
}

TEST_F (I_ElementTest, CFASTTest)
{
    SG::DataStructure::FEM::CFASTData data;
    data.m_id = 100012;
    service->Add (data);

    SG::DataStructure::FEM::CFASTData _OUT outData;
    service->FindById (100012, outData);
    ASSERT_EQ (outData.m_id, 100012);

    ASSERT_EQ (service->FindByIndex (0, outData), SG::DataStructure::Common::Status::STATUS_Success);

    ASSERT_EQ (outData.m_id, 100012);

    ASSERT_EQ (service->Size<CFASTData> (), 1);
    ASSERT_EQ (service->Count<CFASTData> (100012), 1);
}

TEST_F (I_ElementTest, CMASS1Test)
{
    SG::DataStructure::FEM::CMASS1Data data;
    data.m_id = 100013;
    service->Add (data);

    SG::DataStructure::FEM::CMASS1Data _OUT outData;
    service->FindById (100013, outData);
    ASSERT_EQ (outData.m_id, 100013);

    ASSERT_EQ (service->FindByIndex (0, outData), SG::DataStructure::Common::Status::STATUS_Success);

    ASSERT_EQ (outData.m_id, 100013);

    ASSERT_EQ (service->Size<CMASS1Data> (), 1);
    ASSERT_EQ (service->Count<CMASS1Data> (100013), 1);
}
TEST_F (I_ElementTest, CMASS2Test)
{
    SG::DataStructure::FEM::CMASS2Data data;
    data.m_id = 100014;
    service->Add (data);

    SG::DataStructure::FEM::CMASS2Data _OUT outData;
    service->FindById (100014, outData);
    ASSERT_EQ (outData.m_id, 100014);

    ASSERT_EQ (service->FindByIndex (0, outData), SG::DataStructure::Common::Status::STATUS_Success);

    ASSERT_EQ (outData.m_id, 100014);

    ASSERT_EQ (service->Size<CMASS2Data> (), 1);
    ASSERT_EQ (service->Count<CMASS2Data> (100014), 1);
}

TEST_F (I_ElementTest, CMASS3Test)
{
    SG::DataStructure::FEM::CMASS3Data data;
    data.m_id = 100015;
    service->Add (data);

    DB::ServiceFactory->GetDatabase ()->SetPartitionElement ({ 100015 });

    SG::DataStructure::FEM::CMASS3Data _OUT outData;
    service->FindById (100015, outData);
    ASSERT_EQ (outData.m_id, 100015);

    ASSERT_EQ (service->FindByIndex (0, outData), SG::DataStructure::Common::Status::STATUS_Success);

    ASSERT_EQ (outData.m_id, 100015);

    ASSERT_EQ (service->Size<CMASS3Data> (), 1);
    ASSERT_EQ (service->Count<CMASS3Data> (100015), 1);

    DB::ServiceFactory->GetDatabase ()->ClearPartitionElement ();
}

TEST_F (I_ElementTest, CMASS4Test)
{
    SG::DataStructure::FEM::CMASS4Data data;
    data.m_id = 100016;
    service->Add (data);

    SG::DataStructure::FEM::CMASS4Data _OUT outData;
    service->FindById (100016, outData);
    ASSERT_EQ (outData.m_id, 100016);

    ASSERT_EQ (service->FindByIndex (0, outData), SG::DataStructure::Common::Status::STATUS_Success);

    ASSERT_EQ (outData.m_id, 100016);

    ASSERT_EQ (service->Size<CMASS4Data> (), 1);
    ASSERT_EQ (service->Count<CMASS4Data> (100016), 1);
}

TEST_F (I_ElementTest, CVISCTest)
{
    SG::DataStructure::FEM::CVISCData data;
    data.m_id  = 100017;
    data.m_pId = 222;
    service->Add (data);

    SG::DataStructure::FEM::CVISCData _OUT outData;
    service->FindById (100017, outData);
    ASSERT_EQ (outData.m_id, 100017);

    ASSERT_EQ (service->FindByIndex (0, outData), SG::DataStructure::Common::Status::STATUS_Success);

    ASSERT_EQ (outData.m_id, 100017);

    ASSERT_EQ (service->Size<CVISCData> (), 1);
    ASSERT_EQ (service->Count<CVISCData> (100017), 1);
}

TEST_F (I_ElementTest, CHBDYGTest)
{
    SG::DataStructure::FEM::CHBDYGData data;
    data.m_id = 100018;
    service->Add (data);

    SG::DataStructure::FEM::CHBDYGData _OUT outData;
    service->FindById (data.m_id, outData);
    ASSERT_EQ (outData.m_id, data.m_id);

    ASSERT_EQ (service->FindByIndex (0, outData), SG::DataStructure::Common::Status::STATUS_Success);
    ASSERT_EQ (outData.m_id, data.m_id);

    ASSERT_EQ (service->Size<CHBDYGData> (), 1);
    ASSERT_EQ (service->Count<CHBDYGData> (data.m_id), 1);
}

TEST_F (I_ElementTest, SummaryRepository)
{
    // FindElementNodes
    ASSERT_EQ (service->FindElementNodes (38).size (), 8);

    auto nodelist = service->FindElementNodes (8);
    ASSERT_EQ (nodelist.size (), 4);
    ASSERT_EQ (nodelist[3], 4);
    ASSERT_EQ (nodelist[2], 3);
    ASSERT_EQ (nodelist[1], 2);
    ASSERT_EQ (nodelist[0], 1);

    std::vector<SG::DataStructure::FEM::ElementTypes> const types = service->GetAllElementTypes ();
    ASSERT_EQ (types.size (), 36);

    ASSERT_EQ (service->GetElementType (15), SG::DataStructure::FEM::ElementTypes::ELETYPE_ShellTria3);

    ASSERT_EQ (service->GetElementSize (SG::DataStructure::FEM::ElementTypes::ELETYPE_ShellTria3), 1);

    SG::Algebra::Matrix m = service->GetElementNodes (SG::DataStructure::FEM::ElementTypes::ELETYPE_ShellTria3);
    ASSERT_EQ (m[0][1], 2);
    ASSERT_EQ (m[0][2], 3);

    m = service->GetElementNodes (SG::DataStructure::FEM::ElementTypes::ELETYPE_Pyram13);
    for (size_t i = 0; i < 13; i++)
    {
        ASSERT_EQ (m[0][i], 8);
    }

    // 测试FindElement
    // ASSERT_EQ (service->FindElement (100001).second, 0);
    // ASSERT_EQ (service->FindElement (100002).second, 1);
    // ASSERT_EQ (service->FindElement (100018).second, 0);

    auto eIds = service->GetAllElementId ();
    ASSERT_TRUE (std::find (eIds.begin (), eIds.end (), 100018) != eIds.end ());

    auto p2e = service->FindElementByPropId (1);
    ASSERT_EQ (p2e.size (), 3);
    p2e = service->FindElementByPropId (222);
    ASSERT_EQ (p2e.front (), 100017);

    // 测试GetElementIdsByType新接口
    // 测试获取ShellTria3类型的所有单元ID
    auto tria3Ids = service->GetElementIdsByType (SG::DataStructure::FEM::ElementTypes::ELETYPE_ShellTria3);
    ASSERT_EQ (tria3Ids.size (), 1);
    ASSERT_EQ (tria3Ids[0], 15);

    // 测试获取Bar类型的所有单元ID (CBAR)
    auto barIds = service->GetElementIdsByType (SG::DataStructure::FEM::ElementTypes::ELETYPE_Bar);
    ASSERT_EQ (barIds.size (), 2);
    ASSERT_TRUE (std::find (barIds.begin (), barIds.end (), 100001) != barIds.end ());
    ASSERT_TRUE (std::find (barIds.begin (), barIds.end (), 100002) != barIds.end ());

    // 测试获取Hexa8类型的所有单元ID
    auto hexa8Ids = service->GetElementIdsByType (SG::DataStructure::FEM::ElementTypes::ELETYPE_Hexa8SRI);
    ASSERT_EQ (hexa8Ids.size (), 1);
    ASSERT_EQ (hexa8Ids[0], 38);

    // 测试获取不存在类型的单元ID
    auto unknownIds = service->GetElementIdsByType (SG::DataStructure::FEM::ElementTypes::ELETYPE_Unknown);
    ASSERT_TRUE (unknownIds.empty ());

    // 测试获取Pyram13类型的所有单元ID
    auto pyram13Ids = service->GetElementIdsByType (SG::DataStructure::FEM::ElementTypes::ELETYPE_Pyram13);
    ASSERT_EQ (pyram13Ids.size (), 1);
    ASSERT_EQ (pyram13Ids[0], 1713);

    // 验证GetElementIdsByType与GetElementSize的一致性
    for (const auto& type : service->GetAllElementTypes ())
    {
        auto typeIds  = service->GetElementIdsByType (type);
        auto typeSize = service->GetElementSize (type);
        ASSERT_EQ (typeIds.size (), typeSize) << "Type size mismatch for element type: " << static_cast<int> (type);
    }
}

#include <random>

// 測試效率
TEST_F (I_ElementTest, QueryShellPropId)
{
    GTEST_SKIP () << "This test is skipped because it takes too long to run. It is only used for performance testing.";
    // 测试QueryShellPropId查询效率，随机查询1000000次，记录时间
    auto start = std::chrono::high_resolution_clock::now ();

    // 首先添加100000個QUAD4 與 TRIA3 屬性ID均不同吧
    SG::DataStructure::FEM::CQUAD4Data obj;
    for (int i = 0; i < 5000000; ++i)
    {
        obj.m_id  = i;
        obj.m_pId = i;
        // 添加对象
        service->Add (obj);
    }
    std::cout << "Added 10000000 QUAD4 elements  "
              << std::chrono::duration_cast<std::chrono::seconds> (std::chrono::high_resolution_clock::now () - start).count ()
              << " seconds\n";
    SG::DataStructure::FEM::CTRIA3Data ctia;
    for (int i = 5000000; i < 10000000; ++i)
    {
        ctia.m_id  = i;
        ctia.m_pId = i;
        // 添加对象
        service->Add (ctia);
    }
    std::cout << "Added 10000000 TRIA3 elements  "
              << std::chrono::duration_cast<std::chrono::seconds> (std::chrono::high_resolution_clock::now () - start).count ()
              << " seconds\n";

    std::random_device            rd;                     // 获取随机数种子
    std::mt19937                  gen (rd ());            // 使用Mersenne Twister算法生成随机
    std::uniform_int_distribution dis (0, 10000000 - 1000);  // 生成0~20000000的随机数
    // 生成0~20000000的半随机id,每100次随机一次，然后++
    SG::DataStructure::Common::Id halfRandomId = 0;
    for (int i = 0; i < 1000000; ++i)
    {
        if (i % 100 == 0)
        {
            halfRandomId = dis (gen);
            // std::cout << "i = " << i << "  Generated half-random ID: " << halfRandomId << '\n';
        }
        service->QueryShellPropId (++halfRandomId);
    }
    std::cout << "QueryShellPropId took: "
              << std::chrono::duration_cast<std::chrono::seconds> (std::chrono::high_resolution_clock::now () - start).count ()
              << " seconds\n";
}

TEST_F (I_ElementTest, nodeIdFindElementIdTest)
{
    std::vector<SG::DataStructure::Common::Id> nids = service->FindElementNodes (38);
    ASSERT_EQ (service->FindElementNodes (38).size (), 8);

    std::vector<SG::DataStructure::Common::Id> const eids = service->GetElementIdByNode (nids[0]);

    ASSERT_EQ (eids.size (), 117);
}

TEST_F (I_ElementTest, PartitionElementCacheRepository)
{
    auto service = DB::ServiceFactory->get<IPartitionElementCacheService> ();

    // 测试数据准备 - 首先添加一些分区缓存数据
    SG::DBManager::TwoLayersData partition1;
    partition1.m_id   = 1;
    partition1.m_subs = { { 101 }, { 102 }, { 103 }, { 104 }, { 105 } };

    SG::DBManager::TwoLayersData partition2;
    partition2.m_id   = 2;
    partition2.m_subs = { { 201 }, { 202 }, { 203 } };

    SG::DBManager::TwoLayersData partition3;
    partition3.m_id   = 3;
    partition3.m_subs = { { 301 }, { 302 }, { 303 }, { 304 }, { 305 }, { 306 } };

    // 添加分区数据到服务
    service->Add (partition1);
    service->Add (partition2);
    service->Add (partition3);

    // 测试基本的查找功能
    SG::DBManager::TwoLayersData foundPartition;
    ASSERT_EQ (service->FindByIndex (0, foundPartition), SG::DataStructure::Common::Status::STATUS_Success);
    ASSERT_TRUE (foundPartition.m_id >= 1 && foundPartition.m_id <= 3);

    // 测试根据分区ID获取单元
    std::vector<SG::DataStructure::Common::Id> elements1 = service->GetElementsByPartition (1);
    ASSERT_EQ (elements1.size (), 5);
    ASSERT_EQ (elements1[0], 101);
    ASSERT_EQ (elements1[4], 105);

    std::vector<SG::DataStructure::Common::Id> elements2 = service->GetElementsByPartition (2);
    ASSERT_EQ (elements2.size (), 3);
    ASSERT_EQ (elements2[0], 201);
    ASSERT_EQ (elements2[2], 203);

    // 测试获取所有分区
    std::vector<SG::DBManager::TwoLayersData> const allPartitions = service->GetAllData ();
    ASSERT_EQ (allPartitions.size (), 3);

    // 测试数据持久性 - 验证数据已经保存到数据库
    ASSERT_EQ (service->Size (), 3);

    // 测试不存在的分区
    std::vector<SG::DataStructure::Common::Id> const emptyElements = service->GetElementsByPartition (999);
    ASSERT_TRUE (emptyElements.empty ());
}

TEST_F (I_ElementTest, PartitionElementCacheAPITest)
{
    // 清理现有的分区缓存数据 - 重新初始化数据库
    DB::ServiceFactory->ClearDatabase ();

    // 测试DBAPI接口

    // 准备测试数据 - 使用不同的分区ID避免与Repository测试冲突
    std::map<SG::DataStructure::Common::Id, std::vector<SG::DataStructure::Common::Id>> partitionData;

    // 分区10: 包含5个单元
    partitionData[10] = { 1001, 1002, 1003, 1004, 1005 };

    // 分区20: 包含3个单元
    partitionData[20] = { 2001, 2002, 2003 };

    // 分区30: 包含4个单元
    partitionData[30] = { 3001, 3002, 3003, 3004 };

    // 调用API保存分区结果
    SG::DataStructure::Common::Status const saveResult = SG::DBManager::DBAPI::SavePartitionResults (DB::ServiceFactory, partitionData);
    ASSERT_EQ (saveResult, SG::DataStructure::Common::Status::STATUS_Success);

    // 测试获取特定分区的单元
    std::vector<SG::DataStructure::Common::Id> partition10Elements = SG::DBManager::DBAPI::GetPartitionElements (DB::ServiceFactory, 10);
    ASSERT_EQ (partition10Elements.size (), 5);
    ASSERT_EQ (partition10Elements[0], 1001);
    ASSERT_EQ (partition10Elements[4], 1005);

    std::vector<SG::DataStructure::Common::Id> partition20Elements = SG::DBManager::DBAPI::GetPartitionElements (DB::ServiceFactory, 20);
    ASSERT_EQ (partition20Elements.size (), 3);
    ASSERT_EQ (partition20Elements[0], 2001);
    ASSERT_EQ (partition20Elements[2], 2003);

    std::vector<SG::DataStructure::Common::Id> partition30Elements = SG::DBManager::DBAPI::GetPartitionElements (DB::ServiceFactory, 30);
    ASSERT_EQ (partition30Elements.size (), 4);
    ASSERT_EQ (partition30Elements[0], 3001);
    ASSERT_EQ (partition30Elements[3], 3004);

    // 测试获取所有分区结果
    // std::map<SG::DataStructure::Common::Id, std::vector<SG::DataStructure::Common::Id>> allResults =
    //     SG::DBManager::DBAPI::GetAllPartitionResults (DB::ServiceFactory);
    // ASSERT_GE (allResults.size (), 3);  // 至少包含我们新添加的3个分区

    // // 验证新添加的分区数据完整性
    // ASSERT_EQ (allResults.at (10).size (), 5);
    // ASSERT_EQ (allResults.at (10)[0], 1001);
    // ASSERT_EQ (allResults.at (20).size (), 3);
    // ASSERT_EQ (allResults.at (20)[0], 2001);
    // ASSERT_EQ (allResults.at (30).size (), 4);
    // ASSERT_EQ (allResults.at (30)[0], 3001);

    // 测试获取不存在的分区
    std::vector<SG::DataStructure::Common::Id> const emptyResult = SG::DBManager::DBAPI::GetPartitionElements (DB::ServiceFactory, 999);
    ASSERT_TRUE (emptyResult.empty ());
}

#ifdef SG_USE_MPI
TEST_F (I_ElementTest, MPIElementTest)
{
    DB::ServiceFactory->ClearDatabase ();

    auto service = DB::ServiceFactory->get<IElementService> ();

    for (int i = 0; i < 10; ++i)
    {
        SG::DataStructure::FEM::CMASS3Data data;
        data.m_id = 1000 + i;
        service->Add (data);
    }
    ASSERT_EQ (service->Size<CMASS3Data> (), 10);

    DB::ServiceFactory->GetDatabase ()->SetPartitionElement ({ 1002, 1003, 1004, 1005, 1006 });

    auto ids = service->GetAllId<CMASS3Data> ();

    ASSERT_EQ (ids.size (), 5);

    SG::DataStructure::FEM::CMASS3Data testData;
    service->FindByIndex (0, testData);
    ASSERT_EQ (testData.m_id, 1002);

    SG::DataStructure::FEM::CMASS2Data data;
    data.m_id = 2000;
    service->Add (data);

    std::vector<ElementTypes> types = service->GetAllElementTypes ();
    ASSERT_EQ (types.size (), 2);
    ASSERT_EQ (types[0], SG::DataStructure::FEM::ElementTypes::ELETYPE_MASS2);
    ASSERT_EQ (types[1], SG::DataStructure::FEM::ElementTypes::ELETYPE_MASS3);

    ASSERT_EQ (service->GetElementType (1002), SG::DataStructure::FEM::ElementTypes::ELETYPE_MASS3);

    ASSERT_EQ (service->GetElementSize (types[1]), 10);

    ASSERT_EQ (service->GetElementIdsByType (types[1]).size (), 5);

    ASSERT_EQ (service->GetAllElementId ().size (), 5);

    DB::ServiceFactory->GetDatabase ()->ClearPartitionElement ();
}
#endif